package org.road0329.dlt698.asn1.axdr;

import org.road0329.dlt698.ReverseByteArrayInputStream;
import org.road0329.dlt698.ReverseByteArrayOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;

public class AxdrBitString extends AxdrType {
    private static Logger logger = LoggerFactory.getLogger(AxdrBitString.class);
    private byte[] bitString = null;
    private int numBits = 0;
    private boolean fixedLength = false;

    public AxdrBitString() {
    }

    public void setNumBit(int numBits) {
        this.numBits = numBits;
        this.fixedLength = true;
    }

    public void setBitString(byte[] value) {
        this.bitString = value;
        this.fixedLength = true;
    }

    public int encode(ReverseByteArrayOutputStream output) throws Exception {
        if (this.bitString == null) {
            throw new Exception("bitString is null");
        } else {
            int codeLength = this.bitString.length;
            for (int i = this.bitString.length - 1; i >= 0; --i) {
                output.write(this.bitString[i]);
            }
            if (!this.fixedLength) {
                AxdrLength length = new AxdrLength(this.numBits);
                codeLength += length.encode(output);
            }
            return codeLength;
        }
    }

    public int decode(ReverseByteArrayInputStream input) throws Exception {
        int codeLength = 0;
        if (!this.fixedLength) {
            AxdrLength l = new AxdrLength(0);
            codeLength += l.decode(input);
            this.numBits = l.getValue();
        }
        int byteArrayLength = this.numBits % 8 == 0 ? this.numBits / 8 : this.numBits / 8 + 1;
        codeLength += byteArrayLength;
        this.bitString = new byte[byteArrayLength];
        try {
            if (byteArrayLength != 0 && input.read(this.bitString, 0, byteArrayLength) < byteArrayLength) {
                throw new Exception("Error Decoding AxdrBitString");
            }
        } catch (IOException e) {
            logger.info("Error Decoding AxdrBitString.", e);
            throw new Exception("Error Decoding AxdrBitString");
        }
        return codeLength;
    }

    public byte[] getValue() throws Exception {
        if (this.bitString == null) {
            throw new Exception("bitString is null");
        } else {
            return this.bitString;
        }
    }

    public int getNumBits() {
        return this.numBits;
    }

    @Override
    public String toString() {
        if (this.bitString == null) {
            return "bitString is null";
        } else {
            StringBuilder s = new StringBuilder();
            for (int i = 0; i < this.numBits; i++) {
                if (((this.bitString[i / 8] & 0xff) & (0x80 >> (i % 8))) == (0x80 >> (i % 8))) {
                    s.append('1');
                } else {
                    s.append('0');
                }
            }
            return s.toString();
        }
    }
}



